﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace OserverDesignPattern
{
    public class TemperatureMonitor : IObservable<Temperature>
    {
        private IList<IObserver<Temperature>> observers;

        private class Unsubscriber : IDisposable
        {
            private IList<IObserver<Temperature>> observers;
            private IObserver<Temperature> observer;

            public Unsubscriber(IList<IObserver<Temperature>> observers, IObserver<Temperature> observer)
            {
                this.observers = observers;
                this.observer = observer;
            }

            public void Dispose()
            {
                if (!(observer == null)) observers.Remove(observer);
            }
        }

        public TemperatureMonitor()
        {
            observers = new List<IObserver<Temperature>>();
        }

        public IDisposable Subscribe(IObserver<Temperature> observer)
        {
            if (!observers.Contains(observer))
                observers.Add(observer);

            return new Unsubscriber(observers, observer);
        }

        public void GetTemperature()
        {
            Nullable<Decimal>[] temps = {14.6m, 14.65m, 14.7m, 14.9m, 14.9m, 15.2m, 15.25m, 15.2m,
                                15.4m, 15.45m, null };
            
            Nullable<Decimal> previous = 0;

            foreach (var temp in temps)
            {
                System.Threading.Thread.Sleep(2500);
                if (temp.HasValue)
                {
                    if ((Math.Abs(temp.Value - previous.Value) >= 0.1m))
                    {
                        Temperature tempData = new Temperature(temp.Value, DateTime.Now);

                        foreach (var observer in observers)
                        {
                            observer.OnNext(tempData);
                        }

                        previous = temp;
                    }
                }
                else
                {
                    foreach (var observer in observers.ToArray())
                    {
                        if (observer != null)
                        {
                            observer.OnCompleted();
                        }
                    }

                    observers.Clear();
                    break;
                }
            }
        }
    }
}
